# https://gitee.com/yueyinqiu5990/tj12413601/blob/master/assignment1/question2/calculators/simpsons_method.py
import typing

from question2.integration_calculator import Integration1dCalculatorAdaptive
from question2.integration_problem import IntegrationProblem1d


class SimpsonsMethod(Integration1dCalculatorAdaptive):
    def _generate_steps_endlessly(
            self,
            problem: IntegrationProblem1d) \
            -> typing.Generator[float, None, None]:
        # TODO: 利用上次计算结果
        # 最好利用上次计算结果进行下次计算而非重新计算
        for i in Integration1dCalculatorAdaptive.endless_range(2, 2):
            yield SimpsonsMethod.__simpsons(problem, i)

    @staticmethod
    def __simpsons(problem: IntegrationProblem1d, n_positive_even: int):
        assert n_positive_even % 2 == 0 and n_positive_even > 0
        a = problem.lower_limit()
        b = problem.upper_limit()
        f = problem.integrand()
        h = (b - a) / n_positive_even
        # 奇偶分开求和再相加，以免单个值太小导致问题
        sum_odd = 0
        for i in range(1, n_positive_even, 2):
            sum_odd += f(a + i * h)
        sum_even = 0
        # 课件里的公式好像有问题，它不应该取到 n
        for i in range(2, n_positive_even, 2):
            sum_even += f(a + i * h)
        return h / 3 * (f(a) + f(b) + 4 * sum_odd + 2 * sum_even)
